home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / bash / bash_108 / bash-108.zoo / src / variables.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-12  |  38.0 KB  |  1,603 lines

  1. /* variables.c -- Functions for hacking shell variables. */
  2.  
  3. /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
  4.  
  5.    This file is part of GNU Bash, the Bourne Again SHell.
  6.  
  7.    Bash is free software; you can redistribute it and/or modify it
  8.    under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 1, or (at your option)
  10.    any later version.
  11.  
  12.    Bash is distributed in the hope that it will be useful, but WITHOUT
  13.    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  14.    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
  15.    License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with Bash; see the file COPYING.  If not, write to the Free
  19.    Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <pwd.h>
  24. #include <sys/types.h>
  25.  
  26. #include "shell.h"
  27. #include "hash.h"
  28. #include "flags.h"
  29.  
  30. #if defined (USG) && !defined (isc386)
  31. struct passwd *getpwuid (), *getpwent ();
  32. #endif
  33.  
  34. /* The list of shell variables that the user has created, or that came from
  35.    the environment. */
  36. HASH_TABLE *shell_variables = (HASH_TABLE *)NULL;
  37.  
  38. /* The list of shell functions that the user has created, or that came from
  39.    the environment. */
  40. HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
  41.  
  42. /* The current variable context.  This is really a count of how deep into
  43.    executing functions we are. */
  44. int variable_context = 0;
  45.  
  46. /* The array of shell assignments which are made only in the environment
  47.    for a single command. */
  48. char **temporary_env = (char **)NULL;
  49.  
  50. /* Some funky variables which are known about specially.  Here is where
  51.    "$*", "$1", and all the cruft is kept. */
  52. char *dollar_vars[10];
  53. WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
  54.  
  55. /* The value of $$. */
  56. int dollar_dollar_pid;
  57.  
  58. /* An array which is passed to commands as their environment.  It is
  59.    manufactured from the overlap of the initial environment and the
  60.    shell variables that are marked for export. */
  61. char **export_env = (char **)NULL;
  62.  
  63. /* Non-zero means that we have to remake EXPORT_ENV. */
  64. int array_needs_making = 1;
  65.  
  66. /* The list of variables that may not be unset in this shell. */
  67. char **non_unsettable_vars = (char **)NULL;
  68.  
  69. /**
  70.  **  (sjk)++ Remove all mail references on the Atari ST 
  71.  **/
  72. #if !defined(atarist)   
  73. #if defined (USG)
  74. #define DEFAULT_MAIL_PATH "/usr/mail/"
  75. #else
  76. #define DEFAULT_MAIL_PATH "/usr/spool/mail/"
  77. #endif
  78. #endif 
  79.  
  80. /* Some forward declarations. */
  81. SHELL_VAR *set_if_not ();    /* returns new or existing entry */
  82. int set_auto_export ();        /* sets for SHELL_VAR *, not for a name */
  83.  
  84. static void sbrand ();        /* set bash random number generator */
  85.  
  86. /* Initialize the shell variables from the current environment. */
  87. initialize_shell_variables (env)
  88.      char *env[];
  89. {
  90.   extern char *primary_prompt, *secondary_prompt;
  91.   char *name, *string;
  92.   int c, char_index;
  93.   int string_index = 0;
  94.   SHELL_VAR *temp_var;
  95.  
  96.   if (!shell_variables)
  97.     shell_variables = make_hash_table (0);
  98.  
  99.   if (!shell_functions)
  100.     shell_functions = make_hash_table (0);
  101.  
  102.   while (string = env[string_index++])
  103.     {
  104.       char_index = 0;
  105.  
  106.       name = (char *)alloca (1 + strlen (string));
  107.  
  108.       while ((c = *string++) && c != '=')
  109.     name[char_index++] = c;
  110.  
  111.       name[char_index] = '\0';
  112.  
  113.       /* If exported function, define it now. */
  114.       /* Posix.2 style exported function: name()=value */
  115.       if (strncmp ("() {", string, 4) == 0 ||
  116.       ((name[char_index - 1] == ')' &&
  117.         name[char_index - 2] == '(' &&
  118.         string[0] == '{')))
  119.     {
  120.       char *eval_string;
  121.  
  122.       eval_string = (char *)xmalloc (3 + strlen (string) + strlen (name));
  123.       sprintf (eval_string, "%s %s", name, string);
  124.       parse_and_execute (eval_string, name);
  125.  
  126.       if (name[char_index - 1] == ')')
  127.         name[char_index - 2] = '\0';
  128.       set_func_auto_export (name);
  129.     }
  130.       else
  131.     {
  132.       SHELL_VAR *v;
  133.  
  134.       v = bind_variable (name, string);
  135.       set_auto_export (v);
  136.     }
  137.     }
  138.  
  139.   /* Remember this pid. */
  140.   dollar_dollar_pid = getpid ();
  141.  
  142.   /* Now make our own defaults in case the vars that we think are
  143.      important are missing. */
  144.  
  145. /**
  146.  ** (sjk)++ We set some default environment variables, provided 
  147.  **         that they are not defined.
  148.  **/
  149. #if defined(atarist)
  150.   set_if_not("UNIXMODE","/.,rCLAHdb");   /* Set a default Unixmode */ 
  151.   set_if_not("HOME","/dev/A");
  152.   set_if_not("TERM","vt52");
  153. #endif 
  154.  
  155.   temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
  156.   set_auto_export (temp_var);
  157.  
  158.   temp_var = set_if_not ("TERM", "dumb");
  159.   set_auto_export (temp_var);
  160.  
  161.   set_if_not ("PS1", primary_prompt);
  162.   set_if_not ("PS2", secondary_prompt);
  163.   set_if_not ("IFS", " \t\n");
  164.  
  165.   /* Magic machine types.  Pretty convenient. */
  166.   temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
  167.   set_auto_export (temp_var);
  168.  
  169. /**
  170.  **  (sjk)++ Remove all mail references on the Atari ST 
  171.  **/
  172. #if !defined(atarist)   
  173.   /* Default MAILPATH, and MAILCHECK. */
  174.   set_if_not ("MAILCHECK", "60");
  175.   if ((get_string_value ("MAIL") == (char *)NULL) &&
  176.       (get_string_value ("MAILPATH") == (char *)NULL))
  177.     {
  178.       extern char *current_user_name;
  179.       char *tem;
  180.  
  181.       tem = (char *)xmalloc (1 + sizeof (DEFAULT_MAIL_PATH)
  182.                + strlen (current_user_name));
  183.       strcpy (tem, DEFAULT_MAIL_PATH);
  184.       strcat (tem, current_user_name);
  185.  
  186.       bind_variable ("MAILPATH", tem);
  187.       free (tem);
  188.     }
  189. #endif
  190.  
  191.   /* Set up $PWD. */
  192.   {
  193.     char *get_working_directory (), *cd;
  194.  
  195.     cd = get_working_directory ("shell-init");
  196.     if (cd)
  197.       {
  198.     bind_variable ("PWD", cd);
  199.     free (cd);
  200.       }
  201.   }
  202.  
  203.   /* Do some things with shell level. */
  204.   temp_var = set_if_not ("SHLVL", "0");
  205.   set_auto_export (temp_var);
  206.   adjust_shell_level (1);
  207.  
  208.   /* Make a variable $PPID, which holds the pid of the shell's parent.  */
  209.   {
  210.     char *ppid;
  211.     SHELL_VAR *v;
  212.     extern char *itos ();
  213.  
  214.     ppid = itos ((int) getppid ());
  215.     v = find_variable ("PPID");
  216.  
  217.     if (v)
  218.       v->attributes &= ~att_readonly;
  219.  
  220.     v = bind_variable ("PPID", ppid);
  221.     v->attributes |= (att_readonly | att_integer);
  222.  
  223.     non_unsettable ("PPID");
  224.     free (ppid);
  225.   }
  226.  
  227.   /* Initialize the `getopts' stuff. */
  228.   bind_variable ("OPTIND", "1");
  229.   bind_variable ("OPTERR", "1");
  230.  
  231.   /* Get the full pathname to THIS shell, and set the BASH variable
  232.      to it. */
  233.   {
  234.     extern char *shell_name, *find_user_command (), *full_pathname ();
  235.     extern int login_shell;
  236.     char *tname = find_user_command (shell_name);
  237.  
  238.     if ((login_shell == 1) && (*shell_name != '/'))
  239.       {
  240.     struct passwd *entry = getpwuid (getuid ());
  241.  
  242.     if (entry)
  243.       {
  244.         /* If HOME doesn't exist, set it. */
  245.         temp_var = (SHELL_VAR *)find_variable ("HOME");
  246.         if (!temp_var)
  247.           {
  248.         temp_var = bind_variable ("HOME", entry->pw_dir);
  249.         temp_var->attributes |= att_exported;
  250.           }
  251.         name = savestring (entry->pw_shell);
  252.       }
  253.     else
  254.       name = savestring ("a.out");
  255.     endpwent ();
  256.       }
  257.     else
  258.       {
  259.     if (!tname)
  260.       {
  261.         char *make_absolute ();
  262.         name = make_absolute (shell_name, get_string_value ("PWD"));
  263.       }
  264.     else
  265.       {
  266.         name = full_pathname (tname);
  267.         free (tname);
  268.       }
  269.       }
  270.  
  271.     /* Make the exported environment variable SHELL be whatever the name of
  272.        this shell is.  Note that the `tset' command looks at this variable
  273.        to determine what style of commands to output; if it ends in "csh",
  274.        then C-shell commands are output, else Bourne shell commands. */
  275.     temp_var = set_if_not ("SHELL", name);
  276.     set_auto_export (temp_var);
  277.  
  278.     /* Make a variable called BASH, which is the name of THIS shell. */
  279.     temp_var = bind_variable ("BASH", name);
  280.     temp_var->attributes |= att_exported;
  281.  
  282.     free (name);
  283.   }
  284.  
  285.   /* Make a variable called BASH_VERSION which contains the version info. */
  286.   {
  287.     char tt[12];
  288.     extern char *dist_version;
  289.     extern int build_version;
  290.  
  291.     sprintf (tt, "%s.%d", dist_version, build_version);
  292.     bind_variable ("BASH_VERSION", tt);
  293.   }
  294.  
  295.   /* Set history variables to defaults, and then do whatever we would
  296.      do if the variable had just been set. */
  297.   {
  298.     char *tilde_expand ();
  299.     char *tem = tilde_expand ("~/.bash_history");
  300.  
  301.     set_if_not ("HISTFILE", tem);
  302.     free (tem);
  303.  
  304.     set_if_not ("HISTSIZE", "50");
  305.     sv_histsize ("HISTSIZE");
  306.   }
  307.  
  308.   /* seed the random number generator */
  309.  
  310.   sbrand (dollar_dollar_pid);
  311.  
  312.   /* If we have inherited `noclobber' from a previous shell, then set
  313.      noclobbering on. */
  314.   {
  315.     extern int noclobber;
  316.  
  317.     noclobber = find_variable ("noclobber") != NULL;
  318.   }
  319.  
  320.   /* Initialize the dynamic variables, and seed their values */
  321.   initialize_dynamic_variables ();
  322.  
  323.   non_unsettable ("PATH");
  324.   non_unsettable ("PS1");
  325.   non_unsettable ("PS2");
  326.   non_unsettable ("IFS");
  327.  
  328.   /* Get the users real user id, and save that in an readonly variable.
  329.      To make the variable *really* readonly, we have added it to a special
  330.      list of vars. */
  331.  
  332.   sv_uids ();
  333.   set_var_read_only ("UID");
  334.   set_var_read_only ("EUID");
  335.  
  336.   non_unsettable ("EUID");
  337.   non_unsettable ("UID");
  338. }
  339.  
  340. adjust_shell_level (change)
  341.      int change;
  342. {
  343.   extern int shell_level;
  344.   extern char *itos ();
  345.   char *new_level;
  346.   int old_level;
  347.  
  348.  
  349.   old_level = atoi (get_string_value ("SHLVL"));
  350.   shell_level = old_level + change;
  351.   new_level = itos (shell_level);
  352.   bind_variable ("SHLVL", new_level);
  353.   free (new_level);
  354. }
  355.  
  356. /* Add NAME to the list of variables that cannot be unset
  357.    if it isn't already there. */
  358. non_unsettable (name)
  359.      char *name;
  360. {
  361.   register int i;
  362.  
  363.   if (!non_unsettable_vars)
  364.     {
  365.       non_unsettable_vars = (char **)xmalloc (1 * sizeof (char *));
  366.       non_unsettable_vars[0] = (char *)NULL;
  367.     }
  368.  
  369.   for (i = 0; non_unsettable_vars[i]; i++)
  370.     if (strcmp (non_unsettable_vars[i], name) == 0)
  371.       return;
  372.  
  373.   non_unsettable_vars = (char **)
  374.     xrealloc ((char *)non_unsettable_vars, (2 + i) * sizeof (char *));
  375.   non_unsettable_vars[i] = savestring (name);
  376.   non_unsettable_vars[i + 1] = (char *)NULL;
  377. }
  378.  
  379. /* Set NAME to VALUE if NAME has no value. */
  380. SHELL_VAR *
  381. set_if_not (name, value)
  382.      char *name, *value;
  383. {
  384.   SHELL_VAR *v = find_variable (name);
  385.  
  386.   if (!v)
  387.     v = bind_variable (name, value);
  388.   return (v);
  389. }
  390.  
  391. /* Map FUNCTION over the variables in VARIABLES.  Return an array of the
  392.    variables that satisfy FUNCTION.  Satisfy means that FUNCTION returns
  393.    a non-zero value for.  A NULL value for FUNCTION means to use all
  394.    variables. */
  395. SHELL_VAR **
  396. map_over (function, var_hash_table)
  397.      Function *function;
  398.      HASH_TABLE* var_hash_table;
  399. {
  400.   register int i;
  401.   register BUCKET_CONTENTS *tlist;
  402.   SHELL_VAR *var, **list = (SHELL_VAR **)NULL;
  403.   int list_index = 0, list_size = 0;
  404.  
  405.   for (i = 0; i < var_hash_table->nbuckets; i++)
  406.     {
  407.       tlist = get_hash_bucket (i, var_hash_table);
  408.  
  409.       while (tlist)
  410.     {
  411.       var = (SHELL_VAR *)tlist->data;
  412.  
  413.       if (!function || (*function) (var))
  414.         {
  415.           if (list_index + 1 >= list_size)
  416.         list = (SHELL_VAR **)
  417.           xrealloc ((char *)list, (list_size += 20) * sizeof (SHELL_VAR *));
  418.  
  419.           list[list_index++] = var;
  420.           list[list_index] = (SHELL_VAR *)NULL;
  421.         }
  422.       tlist = tlist->next;
  423.     }
  424.     }
  425.   return (list);
  426. }
  427.  
  428. int
  429. qsort_var_comp (var1, var2)
  430.      SHELL_VAR **var1, **var2;
  431. {
  432.   return (strcmp ((*var1)->name, (*var2)->name));
  433. }
  434.  
  435. sort_variables (array)
  436.      SHELL_VAR **array;
  437. {
  438.   qsort (array, array_len (array), sizeof (SHELL_VAR *), qsort_var_comp);
  439. }
  440.  
  441. /* Create a NULL terminated array of all the shell variables in TABLE. */
  442. static SHELL_VAR **
  443. all_vars (table)
  444.      HASH_TABLE *table;
  445. {
  446.   SHELL_VAR **list;
  447.  
  448.   list = map_over ((Function *)NULL, table);
  449.   if (list)
  450.     sort_variables (list);
  451.   return (list);
  452. }
  453.  
  454. /* Create a NULL terminated array of all the shell variables. */
  455. SHELL_VAR **
  456. all_shell_variables ()
  457. {
  458.   return (all_vars (shell_variables));
  459. }
  460.  
  461. /* Create a NULL terminated array of all the shell functions. */
  462. SHELL_VAR **
  463. all_shell_functions ()
  464. {
  465.   return (all_vars (shell_functions));
  466. }
  467.  
  468. /* Print VARS to stdout in such a way that they can be read back in. */
  469. print_var_list (list)
  470.      register SHELL_VAR **list;
  471. {
  472.   register int i;
  473.   register SHELL_VAR *var;
  474.  
  475.   for (i = 0; list && (var = list[i]); i++)
  476.     if (!invisible_p (var))
  477.       print_assignment (var);
  478. }
  479.  
  480. #if defined (NOTDEF)
  481. /* Print LIST (a linked list of shell variables) to stdout
  482.    by printing the names, without the values.  Used to support the
  483.    `set +' command. */
  484. print_vars_no_values (list)
  485.      register SHELL_VAR **list;
  486. {
  487.   register int i;
  488.   register SHELL_VAR *var;
  489.  
  490.   for (i = 0; list && (var = list[i]); i++)
  491.     if (!invisible_p (var))
  492.       printf ("%s\n", var->name);
  493. }
  494. #endif
  495.  
  496. /* Print the value of a single SHELL_VAR.  No newline is
  497.    output, but the variable is printed in such a way that
  498.    it can be read back in. */
  499. print_assignment (var)
  500.      SHELL_VAR *var;
  501. {
  502.   if (function_p (var) && var->value)
  503.     {
  504.       printf ("%s=", var->name);
  505.       print_var_function (var);
  506.       printf ("\n");
  507.     }
  508.   else if (var->value)
  509.     {
  510.       printf ("%s=", var->name);
  511.       print_var_value (var);
  512.       printf ("\n");
  513.     }
  514. }
  515.  
  516. /* Print the value cell of VAR, a shell variable.  Do not print
  517.    the name, nor leading/trailing newline. */
  518. print_var_value (var)
  519.      SHELL_VAR *var;
  520. {
  521.   if (var->value)
  522.     printf ("%s", var->value);
  523. }
  524.  
  525. /* Print the function cell of VAR, a shell variable.  Do not
  526.    print the name, nor leading/trailing newline. */
  527. print_var_function (var)
  528.      SHELL_VAR *var;
  529. {
  530.   char *named_function_string ();
  531.  
  532.   if (function_p (var) && var->value)
  533.     printf ("%s", named_function_string ((char *)NULL, var->value, 1));
  534. }
  535.  
  536.  
  537. /* **************************************************************** */
  538. /*                                                                  */
  539. /*                 Dynamic Variable Extension                       */
  540. /*                                                                  */
  541. /* **************************************************************** */
  542.  
  543. /* DYNAMIC VARIABLES
  544.    
  545.    These are variables whose values are generated anew each time they are
  546.    referenced.  These are implemented using a pair of function pointers
  547.    in the struct variable: assign_func, which is called from bind_variable,
  548.    and dynamic_value, which is called from find_variable.
  549.    
  550.    assign_func is called from bind_variable, if bind_variable discovers
  551.    that the variable being assigned to has such a function.  The function
  552.    is called as
  553.       SHELL_VAR *temp = (*(entry->assign_func)) (entry, value)
  554.    and the (SHELL_VAR *)temp is returned as the value of bind_variable.  It
  555.    is usually ENTRY (self).
  556.    
  557.    dynamic_value is called from find_variable to return a `new' value for
  558.    the specified dynamic varible.  If this function is NULL, the variable
  559.    is treated as a `normal' shell variable.  If it is not, however, then
  560.    this function is called like this:
  561.       tempvar = (*(var->dynamic_value)) (var);
  562.    
  563.    Sometimes `tempvar' will replace the value of `var'.  Other times, the
  564.    shell will simply use the string value.  Pretty object-oriented, huh?
  565.    
  566.    Be warned, though: if you `unset' a special variable, it loses its
  567.    special meaning, even if you subsequently set it.
  568.    
  569.    The special assignment code would probably have been better put in
  570.    subst.c: do_assignment, in the same style as
  571.    stupidly_hack_special_variables, but I wanted the changes as
  572.    localized as possible.  */
  573.  
  574. /* The value of $SECONDS.  This is the number of seconds since shell
  575.    invocation, or, the number of seconds since the last assignment + the
  576.    value of the last assignment. */
  577. static long seconds_value_assigned = (long)0;
  578.  
  579. /* Originally defined in shell.c */
  580. extern time_t shell_start_time;
  581.  
  582. SHELL_VAR *
  583. assign_seconds (self, value)
  584.      SHELL_VAR *self;
  585.      char *value;
  586. {
  587.   seconds_value_assigned = atol (value);
  588.   shell_start_time = NOW;
  589.   return (self);
  590. }
  591.  
  592. SHELL_VAR *
  593. get_seconds (var)
  594.      SHELL_VAR *var;
  595. {
  596.   extern char *itos ();
  597.   time_t time_since_start;
  598.   char *p;
  599.  
  600.   time_since_start = NOW - shell_start_time;
  601.   p = itos((int) seconds_value_assigned + time_since_start);
  602.  
  603.   if (var->value)
  604.     free (var->value);
  605.  
  606.   var->attributes |= att_integer;
  607.   var->value = p;
  608.   return (var);
  609. }
  610.  
  611. /* The random number seed.  You can change this by setting RANDOM. */
  612. static unsigned long rseed = 1;
  613.  
  614. /* A linear congruential random number generator based on the ANSI
  615.    C standard.  A more complicated one is overkill.  */
  616.  
  617. /* Returns a pseudo-random number between 0 and 32767. */
  618. static int
  619. brand ()
  620. {
  621.   rseed = rseed * 1103515245 + 12345;
  622.   return ((unsigned int)(rseed / 65536) % 32768);
  623. }
  624.  
  625. /* Set the random number generator seed to SEED. */
  626. static void
  627. sbrand (seed)
  628.      int seed;
  629. {
  630.   rseed = seed;
  631. }
  632.  
  633. static SHELL_VAR *
  634. assign_random (self, value)
  635.      SHELL_VAR *self;
  636.      char *value;
  637. {
  638.   int s = atoi (value);
  639.  
  640.   sbrand (s);
  641.   return (self);
  642. }
  643.  
  644. static SHELL_VAR *
  645. get_random (var)
  646.      SHELL_VAR *var;
  647. {
  648.   int brand (), rv;
  649.   char *p;
  650.   extern char *itos ();
  651.  
  652.   rv = brand ();
  653.   p = itos ((int)rv);
  654.   if (var->value)
  655.     free (var->value);
  656.  
  657.   var->attributes |= att_integer;
  658.   var->value = p;
  659.   return (var);
  660. }
  661.  
  662. /* Function which returns the current line number. */
  663. static SHELL_VAR *
  664. get_lineno (var)
  665.      SHELL_VAR *var;
  666. {
  667.   extern int line_number;
  668.   char *p;
  669.   extern char *itos ();
  670.  
  671.   p = itos (line_number);
  672.   if (var->value)
  673.     free (var->value);
  674.   var->value = p;
  675.   return (var);
  676. }
  677.  
  678. initialize_dynamic_variables ()
  679. {
  680.   SHELL_VAR *v;
  681.  
  682.   v = bind_variable ("SECONDS", (char *)NULL);
  683.   v->dynamic_value = get_seconds;
  684.   v->assign_func = assign_seconds;
  685.  
  686.   v = bind_variable ("RANDOM", (char *)NULL);
  687.   v->dynamic_value = get_random;
  688.   v->assign_func = assign_random;
  689.  
  690.   v = bind_variable ("LINENO", (char *)NULL);
  691.   v->dynamic_value = get_lineno;
  692.   v->assign_func = (DYNAMIC_FUNC *)NULL;
  693. }
  694.  
  695. /* How to get a pointer to the shell variable or function named NAME.
  696.    HASHED_VARS is a pointer to the hash table containing the list
  697.    of interest (either variables or functions). */
  698. SHELL_VAR *
  699. var_lookup (name, hashed_vars)
  700.      char *name;
  701.      HASH_TABLE *hashed_vars;
  702. {
  703.   BUCKET_CONTENTS *bucket;
  704.  
  705.   bucket = find_hash_item (name, hashed_vars);
  706.  
  707.   if (bucket)
  708.     return ((SHELL_VAR *)bucket->data);
  709.   else
  710.     return ((SHELL_VAR *)NULL);
  711. }
  712.  
  713. /* Look up the variable entry whose name matches STRING.
  714.    Returns the entry or NULL. */
  715. SHELL_VAR *
  716. find_variable (name)
  717.      char *name;
  718. {
  719.   SHELL_VAR *var = var_lookup (name, shell_variables);
  720.  
  721.   if (!var)
  722.     return ((SHELL_VAR *)NULL);
  723.   else if (var->dynamic_value)
  724.     return ((*(var->dynamic_value)) (var));
  725.   else
  726.     return (var);
  727. }
  728.  
  729. /* Look up the function entry whose name matches STRING.
  730.    Returns the entry or NULL. */
  731. SHELL_VAR *
  732. find_function (name)
  733.      char *name;
  734. {
  735.   return (var_lookup (name, shell_functions));
  736. }
  737.  
  738. /* Return the string value of a variable.  Return NULL if the variable
  739.    doesn't exist, or only has a function as a value.  Don't cons a new
  740.    string. */
  741. char *
  742. get_string_value (var_name)
  743.      char *var_name;
  744. {
  745.   SHELL_VAR *var = find_variable (var_name);
  746.  
  747.   if (!var)
  748.     return (char *)NULL;
  749.   else
  750.     return (var->value);
  751. }
  752.  
  753. /* Create a local variable referenced by NAME. */
  754. SHELL_VAR *
  755. make_local_variable (name)
  756.      char *name;
  757. {
  758.   SHELL_VAR *new_var, *old_var, *bind_variable ();
  759.   BUCKET_CONTENTS *elt;
  760.  
  761.   /* local foo; local foo;  is a no-op. */
  762.   old_var = find_variable (name);
  763.   if (old_var && old_var->context == variable_context)
  764.     return (old_var);
  765.  
  766.   elt = remove_hash_item (name, shell_variables);
  767.   if (elt)
  768.     {
  769.       old_var = (SHELL_VAR *)elt->data;
  770.       free (elt->key);
  771.       free (elt);
  772.     }
  773.   else
  774.     old_var = (SHELL_VAR *)NULL;
  775.  
  776.   /* If a variable does not already exist with this name, then
  777.      just make a new one. */
  778.   if (!old_var)
  779.     {
  780.       new_var = bind_variable (name, "");
  781.     }
  782.   else
  783.     {
  784.       new_var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  785.  
  786.       new_var->name = savestring (name);
  787.       new_var->value = savestring ("");
  788.  
  789.       new_var->dynamic_value = (DYNAMIC_FUNC *)NULL;
  790.       new_var->assign_func = (DYNAMIC_FUNC *)NULL;
  791.  
  792.       new_var->attributes = 0;
  793.  
  794.       if (exported_p (old_var))
  795.     new_var->attributes |= att_exported;
  796.  
  797.       new_var->prev_context = old_var;
  798.       elt = add_hash_item (savestring (name), shell_variables);
  799.       elt->data = (char *)new_var;
  800.     }
  801.  
  802.   new_var->context = variable_context;
  803.   return (new_var);
  804. }
  805.  
  806. /* Bind a variable NAME to VALUE.  This conses up the name
  807.    and value strings. */
  808. SHELL_VAR *
  809. bind_variable (name, value)
  810.      char *name, *value;
  811. {
  812.   SHELL_VAR *entry = find_variable (name);
  813.  
  814.   if (!entry)
  815.     {
  816.       /* Make a new entry for this variable.  Then do the binding. */
  817.       entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  818.  
  819.       entry->attributes = 0;
  820.       entry->name = savestring (name);
  821.  
  822.       if (value)
  823.     entry->value = savestring (value);
  824.       else
  825.     entry->value = (char *)NULL;
  826.  
  827.       entry->dynamic_value = (DYNAMIC_FUNC *)NULL;
  828.       entry->assign_func = (DYNAMIC_FUNC *)NULL;
  829.  
  830.       /* Always assume variables are to be made at toplevel!
  831.      make_local_variable has the responsibilty of changing the
  832.      variable context. */
  833.       entry->context = 0;
  834.       entry->prev_context = (SHELL_VAR *)NULL;
  835.  
  836.       {
  837.     BUCKET_CONTENTS *elt;
  838.  
  839.     elt = add_hash_item (savestring (name), shell_variables);
  840.     elt->data = (char *)entry;
  841.       }
  842.     }
  843.   else if (entry->assign_func)
  844.     return ((*(entry->assign_func)) (entry, value));
  845.   else
  846.     {
  847.       if (readonly_p (entry))
  848.     {
  849.       report_error ("%s: read-only variable", name);
  850.       return (entry);
  851.     }
  852.  
  853.       /* If this variable has had its type set to integer (via `declare -i'),
  854.      then do expression evaluation on it and store the result.  The
  855.      functions in expr.c (evalexp and bind_int_variable) are responsible
  856.      for turning off the integer flag if they don't want further
  857.      evaluation done. */
  858.       if (integer_p (entry))
  859.     {
  860.       long val, evalexp();
  861.       extern char *itos();
  862.  
  863.       val = evalexp (value);
  864.       /* We cannot free () entry->value before this; what if the string
  865.          we are working is `even=even+2'?  We need the original value
  866.          around while we are doing the evaluation to handle any possible
  867.          recursion. */
  868.       if (entry->value)
  869.         free (entry->value);
  870.  
  871.       entry->value = itos (val);
  872.     }
  873.       else
  874.     {
  875.       if (entry->value)
  876.         free (entry->value);
  877.  
  878.       if (value)
  879.         entry->value = savestring (value);
  880.       else
  881.         entry->value = (char *)NULL;
  882.     }
  883.     }
  884.  
  885.   if (mark_modified_vars)
  886.     entry->attributes |= att_exported;
  887.  
  888.   if (exported_p (entry))
  889.     array_needs_making = 1;
  890.  
  891.   return (entry);
  892. }
  893.  
  894. /* Dispose of the information attached to VAR. */
  895. dispose_variable (var)
  896.      SHELL_VAR *var;
  897. {
  898.   if (!var)
  899.     return;
  900.  
  901.   if (function_p (var))
  902.     dispose_command (var->value);
  903.   else if (var->value)
  904.     free (var->value);
  905.  
  906.   free (var->name);
  907.  
  908.   if (exported_p (var))
  909.     array_needs_making = 1;
  910.  
  911.   free (var);
  912. }
  913.  
  914. /* Unset the variable referenced by NAME. */
  915. unbind_variable (name)
  916.      char *name;
  917. {
  918.   SHELL_VAR *var = find_variable (name);
  919.  
  920.   if (!var)
  921.     return (-1);
  922.  
  923.   if (var->value)
  924.     {
  925.       free (var->value);
  926.       var->value = (char *)NULL;
  927.     }
  928.  
  929.   makunbound (name, shell_variables);
  930.  
  931.   return (0);
  932. }
  933.  
  934. /* Make the variable associated with NAME go away.  HASH_LIST is the
  935.    hash table from which this variable should be deleted (either
  936.    shell_variables or shell_functions).
  937.    Returns non-zero if the variable couldn't be found. */
  938. makunbound (name, hash_list)
  939.      char *name;
  940.      HASH_TABLE *hash_list;
  941. {
  942.   BUCKET_CONTENTS *elt;
  943.   SHELL_VAR *old_var, *new_var;
  944.  
  945.   elt = remove_hash_item (name, hash_list);
  946.  
  947.   if (!elt)
  948.     return (-1);
  949.  
  950.   old_var = (SHELL_VAR *)elt->data;
  951.   new_var = old_var->prev_context;
  952.  
  953.   if (old_var && exported_p (old_var))
  954.     array_needs_making++;
  955.  
  956.   if (new_var)
  957.     {
  958.       /* Has to be a variable, functions don't have previous contexts. */
  959.       BUCKET_CONTENTS *new_elt;
  960.  
  961.       new_elt = add_hash_item (savestring (new_var->name), hash_list);
  962.       new_elt->data = (char *)new_var;
  963.  
  964.       if (exported_p (new_var))
  965.     set_var_auto_export (new_var->name);
  966.     }
  967.  
  968.   free (elt->key);
  969.   free (elt);
  970.  
  971.   dispose_variable (old_var);
  972.   stupidly_hack_special_variables (name);
  973.   return (0);
  974. }
  975.  
  976. /* Remove the variable with NAME if it is a local variable in the
  977.    current context. */
  978. kill_local_variable (name)
  979.      char *name;
  980. {
  981.   SHELL_VAR *temp = find_variable (name);
  982.  
  983.   if (temp && (temp->context == variable_context))
  984.     {
  985.       makunbound (name, shell_variables);
  986.       return (0);
  987.     }
  988.   return (-1);
  989. }
  990.  
  991. /* Get rid of all of the variables in the current context. */
  992. int
  993. variable_in_context (var)
  994.      SHELL_VAR *var;
  995. {
  996.   return (var && var->context == variable_context);
  997. }
  998.  
  999. kill_all_local_variables ()
  1000. {
  1001.   register int i, pass;
  1002.   register SHELL_VAR *var, **list;
  1003.   HASH_TABLE *varlist;
  1004.  
  1005.   for (pass = 0; pass < 2; pass++)
  1006.     {
  1007.       varlist = pass ? shell_functions : shell_variables;
  1008.  
  1009.       list = map_over (variable_in_context, varlist);
  1010.  
  1011.       if (list)
  1012.     {
  1013.       for (i = 0; var = list[i]; i++)
  1014.         makunbound (var->name, varlist);
  1015.  
  1016.       free (list);
  1017.     }
  1018.     }
  1019. }
  1020.  
  1021. /* Delete the entire contents of the hash table. */
  1022. delete_all_variables (hashed_vars)
  1023.      HASH_TABLE *hashed_vars;
  1024. {
  1025.   register int i;
  1026.   register BUCKET_CONTENTS *bucket;
  1027.  
  1028.   for (i = 0; i < hashed_vars->nbuckets; i++)
  1029.     {
  1030.       bucket = hashed_vars->bucket_array[i];
  1031.  
  1032.       while (bucket)
  1033.     {
  1034.       BUCKET_CONTENTS *temp = bucket;
  1035.       SHELL_VAR *var, *prev;
  1036.  
  1037.       bucket = bucket->next;
  1038.  
  1039.       var = (SHELL_VAR *)temp->data;
  1040.  
  1041.       while (var)
  1042.         {
  1043.           prev = var->prev_context;
  1044.           dispose_variable (var);
  1045.  
  1046.           var = prev;
  1047.         }
  1048.  
  1049.       free (temp->key);
  1050.       free (temp);
  1051.     }
  1052.       hashed_vars->bucket_array[i] = (BUCKET_CONTENTS *)NULL;
  1053.     }
  1054. }
  1055.  
  1056. SHELL_VAR *
  1057. new_shell_variable (name)
  1058.      char *name;
  1059. {
  1060.   SHELL_VAR *var;
  1061.  
  1062.   var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  1063.  
  1064.   bzero (var, sizeof (SHELL_VAR));
  1065.   var->name = savestring (name);
  1066.   return (var);
  1067. }
  1068.  
  1069. /* Do a function binding to a variable.  You pass the name and
  1070.    the command to bind to.  This conses the name and command. */
  1071. SHELL_VAR *
  1072. bind_function (name, value)
  1073.      char *name;
  1074.      COMMAND *value;
  1075. {
  1076.   SHELL_VAR *entry = find_function (name);
  1077.  
  1078.   if (!entry)
  1079.     {
  1080.       BUCKET_CONTENTS *elt;
  1081.  
  1082.       elt = add_hash_item (savestring (name), shell_functions);
  1083.  
  1084.       elt->data = (char *)new_shell_variable (name);
  1085.       entry = (SHELL_VAR *)elt->data;
  1086.       entry->dynamic_value = (DYNAMIC_FUNC *)NULL;
  1087.       entry->assign_func = (DYNAMIC_FUNC *)NULL;
  1088.  
  1089.       /* Functions are always made at the top level.  This allows a
  1090.      function to define another function (like autoload). */
  1091.       entry->context = 0;
  1092.     }
  1093.  
  1094.   if (entry->value)
  1095.     dispose_command (entry->value);
  1096.  
  1097.   if (value)    /* I don't think this can happen anymore */
  1098.     entry->value = (char *)copy_command (value);
  1099.   else
  1100.     entry->value = (char *)NULL;
  1101.  
  1102.   entry->attributes |= att_function;
  1103.  
  1104.   if (mark_modified_vars)
  1105.     entry->attributes |= att_exported;
  1106.  
  1107.   entry->attributes &= ~att_invisible;    /* Just to be sure */
  1108.  
  1109.   array_needs_making = 1;
  1110.  
  1111.   return (entry);
  1112. }
  1113.  
  1114. /* Copy VAR to a new data structure and return that structure. */
  1115. SHELL_VAR *
  1116. copy_variable (var)
  1117.      SHELL_VAR *var;
  1118. {
  1119.   SHELL_VAR *copy = (SHELL_VAR *)NULL;
  1120.  
  1121.   if (var)
  1122.     {
  1123.       copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  1124.  
  1125.       copy->attributes = var->attributes;
  1126.       copy->name = savestring (var->name);
  1127.  
  1128.       if (function_p (var))
  1129.     copy->value = (char *)copy_command (var->value);
  1130.       else if (var->value)
  1131.     copy->value = savestring (var->value);
  1132.       else
  1133.     copy->value = (char *)NULL;
  1134.  
  1135.       copy->dynamic_value = var->dynamic_value;
  1136.       copy->assign_func = var->assign_func;
  1137.  
  1138.       copy->context = var->context;
  1139.  
  1140.       /* Don't bother copying previous contexts along with this variable. */
  1141.       copy->prev_context = (SHELL_VAR *)NULL;
  1142.     }
  1143.   return (copy);
  1144. }
  1145.  
  1146. /* Make the variable associated with NAME be read-only.
  1147.    If NAME does not exist yet, create it. */
  1148. set_var_read_only (name)
  1149.      char *name;
  1150. {
  1151.   SHELL_VAR *entry = find_variable (name);
  1152.  
  1153.   if (!entry)
  1154.     {
  1155.       entry = bind_variable (name, "");
  1156.       if (!no_invisible_vars)
  1157.     entry->attributes |= att_invisible;
  1158.     }
  1159.   entry->attributes |= att_readonly;
  1160. }
  1161.  
  1162. /* Make the function associated with NAME be read-only.
  1163.    If NAME does not exist, we just punt, like auto_export code below. */
  1164. set_func_read_only (name)
  1165.      char *name;
  1166. {
  1167.   SHELL_VAR *entry = find_function (name);
  1168.  
  1169.   if (entry)
  1170.     entry->attributes |= att_readonly;
  1171. }
  1172.  
  1173. /* Make VAR be auto-exported.  This is used when a lookup has just
  1174.    been performed, so another one is not needed. */
  1175. set_auto_export (var)
  1176.   SHELL_VAR *var;
  1177. {
  1178.   var->attributes |= att_exported;
  1179.   array_needs_making = 1;
  1180. }
  1181.  
  1182. /* Make the variable associated with NAME be auto-exported.
  1183.    If NAME does not exist yet, create it. */
  1184. set_var_auto_export (name)
  1185.      char *name;
  1186. {
  1187.   SHELL_VAR *entry = find_variable (name);
  1188.  
  1189.   if (!entry)
  1190.     {
  1191.       entry = bind_variable (name, "");
  1192.       if (!no_invisible_vars)
  1193.     entry->attributes |= att_invisible;
  1194.     }
  1195.   entry->attributes |= att_exported;
  1196.   array_needs_making = 1;
  1197. }
  1198.  
  1199. /* Make the function associated with NAME be auto-exported. */
  1200. set_func_auto_export (name)
  1201.      char *name;
  1202. {
  1203.   SHELL_VAR *entry = find_function (name);
  1204.  
  1205.   if (entry)
  1206.     {
  1207.       entry->attributes |= att_exported;
  1208.       array_needs_making = 1;
  1209.     }
  1210. }
  1211.  
  1212. /* Returns non-zero if STRING is an assignment statement.  The returned value
  1213.    is the index of the `=' sign. */
  1214. assignment (string)
  1215.      char *string;
  1216. {
  1217.   register int c, index = 0;
  1218.  
  1219.   c = string[index];
  1220.   if (!isletter (c) && c != '_')
  1221.     return (0);
  1222.  
  1223.   while (c = string[index])
  1224.     {
  1225.       /* The following is safe.  Note that '=' at the start of a word
  1226.      is not an assignment statement. */
  1227.       if (c == '=')
  1228.     return (index);
  1229.  
  1230.       if (!isletter (c) && !digit (c) && c != '_')
  1231.     return (0);
  1232.  
  1233.       index++;
  1234.     }
  1235.   return (0);
  1236. }
  1237.  
  1238. int
  1239. visible_var (var)
  1240.      SHELL_VAR *var;
  1241. {
  1242.   return (!invisible_p (var));
  1243. }
  1244.  
  1245. SHELL_VAR **
  1246. all_visible_variables ()
  1247. {
  1248.   SHELL_VAR **list;
  1249.  
  1250.   list = map_over (visible_var, shell_variables);
  1251.   if (list)
  1252.     sort_variables (list);
  1253.   return (list);
  1254. }
  1255.  
  1256. SHELL_VAR **
  1257. all_visible_functions ()
  1258. {
  1259.   SHELL_VAR **list;
  1260.  
  1261.   list = map_over (visible_var, shell_functions);
  1262.   if (list)
  1263.     sort_variables (list);
  1264.   return (list);
  1265. }
  1266.  
  1267. /* Return non-zero if the variable VAR is visible and exported. */
  1268. int
  1269. visible_and_exported (var)
  1270.      SHELL_VAR *var;
  1271. {
  1272.   return (!invisible_p (var) && exported_p (var));
  1273. }
  1274.  
  1275. /* Make an array of assignment statements from the hash table
  1276.    HASHED_VARS which contains SHELL_VARs.  Only visible, exported
  1277.    variables are eligible. */
  1278. char **
  1279. make_var_array (hashed_vars)
  1280.      HASH_TABLE *hashed_vars;
  1281. {
  1282.   register int i, list_index;
  1283.   register SHELL_VAR *var;
  1284.   char **list = (char **)NULL;
  1285.   SHELL_VAR **vars;
  1286.  
  1287.   vars = map_over (visible_and_exported, hashed_vars);
  1288.  
  1289.   if (!vars)
  1290.     return (char **)NULL;
  1291.  
  1292.   list = (char **)xmalloc ((1 + array_len ((char **)vars)) * sizeof (char *));
  1293.  
  1294.   for (i = 0, list_index = 0; var = vars[i]; i++)
  1295.     {
  1296.       char *value, *named_function_string ();
  1297.  
  1298.       if (function_p (var))
  1299.     {
  1300.       value =
  1301.         named_function_string ((char *)NULL,
  1302.                    (COMMAND *)function_cell (var), 0);
  1303.     }
  1304.       else
  1305.     value = value_cell (var);
  1306.  
  1307.       if (value)
  1308.     {
  1309. #if 0
  1310.       list[list_index] =
  1311.         (char *)xmalloc (2 + strlen (var->name) + strlen (value));
  1312.  
  1313.       sprintf (list[list_index], "%s=%s", var->name, value);
  1314. #else
  1315.       /* Let's see if this makes any kind of performance difference. */
  1316.       int name_len = strlen (var->name);
  1317.       int value_len = strlen (value);
  1318.       char    *p;
  1319.  
  1320.       p = list[list_index] =  (char *)xmalloc (2 + name_len + value_len);
  1321.       strcpy (p, var->name);
  1322.       p[name_len] = '=';
  1323.       strcpy (&p[name_len + 1], value);
  1324. #endif
  1325.       list_index++;
  1326.     }
  1327.     }
  1328.  
  1329.   free (vars);
  1330.   list[list_index] = (char *)NULL;
  1331.   return (list);
  1332. }
  1333.  
  1334. /* Add STRING to the array of foo=bar strings that we already
  1335.    have to add to the environment.  */
  1336. assign_in_env (string)
  1337.      char *string;
  1338. {
  1339.   int size;
  1340.  
  1341.   int offset = assignment (string);
  1342.   char *name = savestring (string);
  1343.   char *temp, *value = (char *)NULL;
  1344.  
  1345.   if (name[offset] == '=')
  1346.     {
  1347.       char *tilde_expand (), *string_list ();
  1348.       WORD_LIST *list, *expand_string_unsplit ();
  1349.  
  1350.       name[offset] = 0;
  1351.       temp = name + offset + 1;
  1352.       temp = tilde_expand (temp);
  1353.  
  1354.       list = expand_string_unsplit (temp, 0);
  1355.       value = string_list (list);
  1356.  
  1357.       if (list)
  1358.     dispose_words (list);
  1359.  
  1360.       free (temp);
  1361.     }
  1362.  
  1363.   if (!value) value = savestring ("");
  1364.  
  1365.   temp = (char *)xmalloc (2 + strlen (name) + strlen (value));
  1366.   sprintf (temp, "%s=%s", name, value);
  1367.   free (name);
  1368.  
  1369.   if (!temporary_env)
  1370.     {
  1371.       temporary_env = (char **)xmalloc (sizeof (char *));
  1372.       temporary_env [0] = (char *)NULL;
  1373.     }
  1374.  
  1375.   size = array_len (temporary_env);
  1376.   temporary_env = (char **)
  1377.     xrealloc ((char *)temporary_env, (size + 2) * (sizeof (char *)));
  1378.  
  1379.   temporary_env[size] = (temp);
  1380.   temporary_env[size + 1] = (char *)NULL;
  1381.   array_needs_making = 1;
  1382.  
  1383.   if (echo_command_at_execute)
  1384.     {
  1385.       /* The K*rn shell prints the `+ ' in front of assignment statements,
  1386.      so we do too. */
  1387.       extern char *indirection_level_string ();
  1388.       fprintf (stderr, "%s%s\n", indirection_level_string (), temp);
  1389.       fflush (stderr);
  1390.     }
  1391. }
  1392.  
  1393. /* Find a variable in the temporary environment that is named NAME.
  1394.    Return a consed variable, or NULL if not found. */
  1395. SHELL_VAR *
  1396. find_tempenv_variable (name)
  1397.      char *name;
  1398. {
  1399.   register int i, l = strlen (name);
  1400.  
  1401.   if (!temporary_env)
  1402.     return ((SHELL_VAR *)NULL);
  1403.  
  1404.   for (i = 0; temporary_env[i]; i++)
  1405.     {
  1406.       if (strncmp (temporary_env[i], name, l) == 0 &&
  1407.       temporary_env[i][l] == '=')
  1408.     {
  1409.       SHELL_VAR *temp;
  1410.  
  1411.       temp = new_shell_variable (name);
  1412.  
  1413.       if (temporary_env[i][l + 1])
  1414.         temp->value = savestring (&temporary_env[i][l + 1]);
  1415.       else
  1416.         temp->value = savestring ("");
  1417.       temp->attributes = att_exported;
  1418.       temp->context = 0;
  1419.       temp->prev_context = (SHELL_VAR *)NULL;
  1420.  
  1421.       temp->dynamic_value = (DYNAMIC_FUNC *)NULL;
  1422.       temp->assign_func = (DYNAMIC_FUNC *)NULL;
  1423.  
  1424.       return (temp);
  1425.     }
  1426.     }
  1427.   return ((SHELL_VAR *)NULL);
  1428. }
  1429.  
  1430. /* Free the storage used in the variable array for temporary
  1431.    environment variables. */
  1432. dispose_used_env_vars ()
  1433. {
  1434.   if (!temporary_env)
  1435.     return;
  1436.  
  1437.   free_array (temporary_env);
  1438.   temporary_env = (char **)NULL;
  1439.   array_needs_making = 1;
  1440. }
  1441.  
  1442. /* Stupid comparison routine for qsort () ing strings. */
  1443. qsort_string_compare (s1, s2)
  1444.      register char **s1, **s2;
  1445. {
  1446.   return (strcmp (*s1, *s2));
  1447. }
  1448.  
  1449. #define ISFUNC(s, o) ((s[o + 1] == '(')  && (s[o + 2] == ')'))
  1450.  
  1451. /* Add ASSIGN to ARRAY, or supercede a previous assignment in the
  1452.    array with the same left-hand side.  Return the new array. */
  1453. char **
  1454. add_or_supercede (assign, array)
  1455.      char *assign;
  1456.      register char **array;
  1457. {
  1458.   register int i;
  1459.   int equal_offset = assignment (assign);
  1460.  
  1461.   if (!equal_offset)
  1462.     return (array);
  1463.  
  1464.   /* If this is a function, then only supercede the function definition.
  1465.      We do this by including the `=(' in the comparison.  */
  1466.   if (assign[equal_offset + 1] == '(')
  1467.     equal_offset++;
  1468.  
  1469.   for (i = 0; array[i]; i++)
  1470.     {
  1471.       if (STREQN (assign, array[i], equal_offset + 1))
  1472.     {
  1473.       free (array[i]);
  1474.       array[i] = savestring (assign);
  1475.       return (array);
  1476.     }
  1477.     }
  1478.   array = (char **)xrealloc ((char *)array, (2 + array_len (array)) * sizeof (char *));
  1479.   array[i++] = savestring (assign);
  1480.   array[i] = (char *)NULL;
  1481.   return (array);
  1482. }
  1483.  
  1484. /* Make the environment array for the command about to be executed.  If the
  1485.    array needs making.  Otherwise, do nothing.  If a shell action could
  1486.    change the array that commands receive for their environment, then the
  1487.    code should `array_needs_making++'. */
  1488. maybe_make_export_env ()
  1489. {
  1490.   register int i;
  1491.   register char **temp_array;
  1492.  
  1493.   if (array_needs_making)
  1494.     {
  1495.       if (export_env)
  1496.     free_array (export_env);
  1497.  
  1498. #ifdef SHADOWED_ENV
  1499.       export_env =
  1500.     (char **)xmalloc ((1 + array_len (shell_environment)) * sizeof (char *));
  1501.  
  1502.       for (i = 0; shell_environment[i]; i++)
  1503.     export_env[i] = savestring (shell_environment[i]);
  1504.       export_env[i] = (char *)NULL;
  1505.  
  1506. #else /* !SHADOWED_ENV */
  1507.  
  1508.       export_env = (char **)xmalloc (sizeof (char *));
  1509.       export_env[0] = (char *)NULL;
  1510.  
  1511. #endif /* SHADOWED_ENV */
  1512.  
  1513.       temp_array = make_var_array (shell_variables);
  1514.       for (i = 0; temp_array && temp_array[i]; i++)
  1515.     export_env = add_or_supercede (temp_array[i], export_env);
  1516.       free_array (temp_array);
  1517.  
  1518.       temp_array = make_var_array (shell_functions);
  1519.       for (i = 0; temp_array && temp_array[i]; i++)
  1520.     export_env = add_or_supercede (temp_array[i], export_env);
  1521.       free_array (temp_array);
  1522.  
  1523.       if (temporary_env)
  1524.     {
  1525.       for (i = 0; temporary_env[i]; i++)
  1526.         export_env = add_or_supercede (temporary_env[i], export_env);
  1527.  
  1528.       /* Sort the array alphabetically. */
  1529.       qsort (export_env, array_len (export_env),
  1530.          sizeof (char *), qsort_string_compare);
  1531.     }
  1532.       array_needs_making = 0;
  1533.     }
  1534. }
  1535.  
  1536. /* We always put _ in the environment as the name of this command. */
  1537. put_command_name_into_env (command_name)
  1538.      char *command_name;
  1539. {
  1540.   char *dummy;
  1541.  
  1542.   dummy = (char *)xmalloc (4 + strlen (command_name));
  1543.  
  1544.   /* These three statements replace a call to sprintf */
  1545.   dummy[0] = '_';
  1546.   dummy[1] = '=';
  1547.   strcpy (&dummy[2], command_name);
  1548.   export_env = add_or_supercede (dummy, export_env);
  1549.   free (dummy);
  1550. }
  1551.  
  1552. /* We supply our own version of getenv () because we want library
  1553.    routines to get the changed values of exported variables. */
  1554. char *last_tempenv_value = (char *)NULL;
  1555.  
  1556. /* The NeXT C library has getenv () defined and used in the same file.
  1557.    This screws our scheme.  However, Bash will run on the NeXT using
  1558.    the C library getenv (), since right now the only environment variable
  1559.    that we care about is HOME, and that is already defined.  */
  1560. #if !defined (NeXT)
  1561. char *
  1562. getenv (name)
  1563.      const char *name;
  1564. {
  1565.   SHELL_VAR *var = find_tempenv_variable (name);
  1566.  
  1567.   if (var)
  1568.     {
  1569.       if (last_tempenv_value)
  1570.     free (last_tempenv_value);
  1571.  
  1572.       last_tempenv_value = savestring (value_cell (var));
  1573.       dispose_variable (var);
  1574.       return (last_tempenv_value);
  1575.     }
  1576.   else if (shell_variables)
  1577.     {
  1578.       var = find_variable (name);
  1579.       if (var && exported_p (var))
  1580.     return (value_cell (var));
  1581.     }
  1582.   else
  1583.     {
  1584.       register int i, len = strlen (name);
  1585.       extern char **environ;
  1586.  
  1587.       /* In some cases, s5r3 invokes getenv() before main(); BSD systems
  1588.          using gprof also exhibit this behavior.  This means that
  1589.          shell_variables will be 0 when this is invoked.  We look up the
  1590.      variable in the real environment in that case. */
  1591.  
  1592.       for (i = 0; environ[i]; i++)
  1593.     {
  1594.       if ((strncmp (environ[i], name, len) == 0) &&
  1595.           (environ[i][len] == '='))
  1596.         return (environ[i] + len + 1);
  1597.     }
  1598.     }
  1599.  
  1600.   return ((char *)NULL);
  1601. }
  1602. #endif /* NeXT */
  1603.